package com.lmn.util;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

public class IdFactoryUtil {
    private static HashMap<String, AtomicInteger> cache = new HashMap<String, AtomicInteger>(1);
    private static final ReentrantLock lock = new ReentrantLock();
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
    private static String ipLast = null;
    private static final char ZERO = '0';

    /**
     * IP后两段，要求输出定长6位，左面补零
     */
    static {
        String ip = null;
        try {
            ip = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String[] ipArray = ip.split("\\.");
        ipLast = flushLeft(3, ipArray[3]);
    }

    /**
     * 获取ID
     *
     * @return 规则：yyMMddHHmmss + 定长一秒内的四位自增数字 + 本机IP的后6位
     */
    public static Long getId() {
        String id = getTimeStampSequence() + ipLast;
        return Long.parseLong(id);
    }

    /**
     * 获取一秒时间内自增的字符串数字
     *
     * @return yyMMddHHmmss + 定长一秒内的四位自增数字
     */
    private static String getTimeStampSequence() {
        String timestamp = null;
        String inc = null;
        lock.lock();
        try {
            timestamp = sdf.format(new Date());
            AtomicInteger value = cache.get(timestamp);
            if (value == null) {
                cache.clear();
                int defaultStartValue = 0;
                cache.put(timestamp, new AtomicInteger(defaultStartValue));
                inc = String.valueOf(defaultStartValue);
            } else {
                inc = String.valueOf(value.addAndGet(1));
            }
        } finally {
            lock.unlock();
        }

        return timestamp + flushLeft(4, inc);
    }

    /**
     * 字符串不满足定长，左边补零处理
     *
     * @param length  填充后的字符串长度
     * @param content 需要处理的字符串
     * @return
     */
    private static String flushLeft(int length, String content) {
        StringBuilder cs = new StringBuilder();
        for (int i = 0, clength = content.length(); i < length - clength; i++) {
            cs.append(ZERO);
        }
        cs.append(content);
        return cs.toString();
    }

}
